package com.gitee.apanlh.util.reflection;

import com.gitee.apanlh.exp.InstanceException;
import com.gitee.apanlh.util.base.CollUtils;
import com.gitee.apanlh.util.base.Empty;
import com.gitee.apanlh.util.base.IteratorUtils;
import com.gitee.apanlh.util.base.MapUtils;
import com.gitee.apanlh.util.base.StringUtils;
import com.gitee.apanlh.util.cache.local.Cache;
import com.gitee.apanlh.util.cache.local.CacheUtils;
import com.gitee.apanlh.util.valid.Assert;
import com.gitee.apanlh.util.valid.ValidParam;

import java.lang.annotation.Annotation;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Map;

/**	
 * 	反射工具类
 * 
 * 	@author Pan
 */
public class ReflectionUtils {
	
	/** 构造器缓存 */
	static final Cache<Class<?>, Constructor<?>[]> CONSTRUCTORS_CACHE 		    = CacheUtils.cache(256);
	/** 方法缓存 */
	static final Cache<Class<?>, Method[]> 		   		METHODS_CACHE 	  		= CacheUtils.cache(256);
	/** 字段缓存 */
	static final FieldProvider 							FIELD_PROVIDER 			= new FieldCache();
	
	/**
	 * 	构造函数
	 * 
	 * 	@author Pan
	 */
	private ReflectionUtils() {
		//	不允许外部实例
		super();
	}
	
	/**
	 * 	扫描类是否同时存在某注解
	 * 	<br>如果其中一个不存在则返回false
	 * 	<br>与条件
	 * 	
	 * 	@author Pan
	 * 	@param 	clazz		类
	 * 	@param 	annotations	注解
	 * 	@return	boolean
	 */
	@SafeVarargs
	public static boolean scanClassAnnotation(Class<?> clazz, Class<? extends Annotation>... annotations) {
		return scanAnnotationAnd(clazz, null, annotations);
	}
	
	/**		 
	 * 	扫描类中字段是否存在某注解
	 * 	<br>存在返回对应注解的{@code List<Field>}
	 * 	<br>true为存在
	 * 	
	 * 	@author Pan
	 * 	@param  <A>      		数据类型
	 * 	@param 	field			字段对象 
	 * 	@param 	annotation		注解
	 * 	@return	boolean
	 */
	public static <A> boolean scanFieldAnnotation(Field field, Class<A> annotation) {
		return ValidParam.isNotNull(getFieldAnnotation(field, annotation));
	}
	
	/**		 
	 * 	扫描类中字段是否存在某注解
	 * 	<br>多个注解时为(与条件)判断
	 * <br>true为存在
	 * 
	 * 	@author Pan
	 * 	@param 	clazz			类
	 * 	@param 	annotations		注解
	 * 	@return	boolean
	 */
	@SafeVarargs
	public static boolean scanFieldAnnotation(Class<?> clazz, Class<? extends Annotation>... annotations) {
		Field[] fields = getFields(clazz);
		
		for (int i = 0, len = fields.length; i < len; i++) {
			Field field = fields[i];
			if (scanAnnotationAnd(null, field, annotations)) {
				return true;
			}
		}
		return false;
	}
	
	
	/**
	 * 	扫描注解
	 * 	<br> 与条件
	 * 
	 * 	@author Pan
	 * 	@param  <T>      			数据类型
	 * 	@param 	clazz				类
	 * 	@param 	accessibleObject	方法、字段对象
	 * 	@param 	annotations			注解
	 * 	@return	boolean	
	 */	
	@SafeVarargs
	public static <T extends AccessibleObject> boolean scanAnnotationAnd(Class<?> clazz, T accessibleObject, Class<? extends Annotation>... annotations) {
		if (clazz == null) {
			for (Class<? extends Annotation> annotation : annotations) {
				if (!accessibleObject.isAnnotationPresent(annotation)) {
					return false;
				}
			}
		} else {
			//	类
			for (Class<? extends Annotation> annotation : annotations) {
				if (!clazz.isAnnotationPresent(annotation)) {
					return false;
				}
			}
		}
		return true;
	}
	
	/**
	 * 	扫描注解
	 * 	<br> 或条件
	 * 	
	 * 	@author Pan
	 * 	@param  <T>      			数据类型
	 * 	@param 	clazz				类
	 * 	@param 	accessibleObject	方法、字段对象
	 * 	@param 	annotations			注解
	 * 	@return	boolean
	 */
	@SafeVarargs
	public static <T extends AccessibleObject> boolean scanAnnotationOr(Class<?> clazz, T accessibleObject, Class<? extends Annotation>... annotations) {
		if (clazz == null) {
			for (Class<? extends Annotation> annotation : annotations) {
				if (accessibleObject.isAnnotationPresent(annotation)) {
					return true;
				}
			}
		} else {
			//	类
			for (Class<? extends Annotation> annotation : annotations) {
				if (clazz.isAnnotationPresent(annotation)) {
					return true;
				}
			}
		}
		return false;
	}
	
	
	/**	
	 * 	获取该类下的所有构造函数
	 * 	
	 * 	@author Pan
	 * 	@param 	clazz	类
	 * 	@return	Constructor[]
	 */
	private static Constructor<?>[] getDeclaredConstructors(Class<?> clazz) {
		return clazz.getDeclaredConstructors();
	}
	
	/**		
	 * 	获取该类下所有构造函数
	 *
	 * 	@author Pan
	 * 	@param 	clazz	类
	 * 	@return	Constructor[]
	 */
	public static Constructor<?>[] getConstructors(Class<?> clazz) {
		Constructor<?>[] constructors = CONSTRUCTORS_CACHE.get(clazz);
		//															获取该类所有构造
		return constructors == null ? CONSTRUCTORS_CACHE.put(clazz, getDeclaredConstructors(clazz)) : constructors;
	}
	
	/**	
	 * 	获取构造函数
	 * 	
	 * 	@author Pan
	 * 	@param  <T>      	数据类型
	 * 	@param 	clazz		类
	 * 	@param 	callTypes	构造参数类型
	 * 	@return	Constructor
	 */
	@SuppressWarnings("unchecked")
	public static <T> Constructor<T> getConstructor(Class<T> clazz, Class<?>... callTypes) {
		Constructor<?>[] constructors = CONSTRUCTORS_CACHE.get(clazz);
		
		//	缓存不存在获取将获取该类所有构造函数
		if (constructors == null) {
			constructors = getConstructors(clazz);
		}
		
		//	因为存在基本类型与包装类 类型问题 所以需要对比正确调用构造函数
		for (int i = 0, len = constructors.length; i < len; i++) {
			Constructor<?> constructor = constructors[i];
			//	获取正确构造函数
			if (compareParamType(constructor.getParameterTypes(), callTypes)) {
				//	开启权限
				setAccessible(constructor);
				return (Constructor<T>) constructor;
			}
		}
		return null;
	}
	
	/**	
	 * 	获取该类下所有方法
	 * 	
	 * 	@author Pan
	 * 	@param 	clazz	类
	 * 	@return	Method[]
	 */
	private static Method[] getDeclaredMethods(Class<?> clazz) {
		return clazz.getDeclaredMethods();
	}
	
	/**
	 * 	获取该类下的某个方法
	 * 	
	 * 	@author Pan
	 * 	@param 	clazz		类
	 * 	@param 	methodName	方法名
	 * 	@return	Method
	 */
	public static Method getMethod(Class<?> clazz, String methodName) {
		Assert.isNotEmpty(methodName);
		
		Method[] methods = getMethods(clazz);
		
		for (int i = 0, len = methods.length; i < len; i++) {
			Method method = methods[i];
			if (StringUtils.eq(method.getName(), methodName)) {
				return method;
			}
		}
		return null;
	}
	
	/**
	 * 	获取该类下的所有方法
	 * 		
	 * 	@author Pan
	 * 	@param 	clazz	类
	 * 	@return	Method[]
	 */
	public static Method[] getMethods(Class<?> clazz) {
		Method[] methods = METHODS_CACHE.get(clazz);
		return methods == null ? METHODS_CACHE.put(clazz, getDeclaredMethods(clazz)): methods;
	}
	
	/**
	 *	根据字段名返回Field
	 *	
	 * 	@author Pan
	 * 	@param  <T>      		数据类型
	 * 	@param 	obj				对象
	 * 	@param 	searchNames		字段名
	 * 	@return	Field
	 */
	public static <T> Field getField(T obj, String searchNames) {
		if (obj == null) {
			return null;
		}
		return FIELD_PROVIDER.getField(obj.getClass(), searchNames);
	}
	
	/**
	 *	根据字段名返回Field
	 *	
	 * 	@author Pan
	 * 	@param 	clazz			类
	 * 	@param 	searchNames		字段名
	 * 	@return	Field
	 */
	public static Field getField(Class<?> clazz, String searchNames) {
		return FIELD_PROVIDER.getField(clazz, searchNames);
	}
	
	/**
	 * 	获取该类下的所有字段
	 * 	<br>默认获取静态字段 
	 * 
	 * 	@author Pan
	 * 	@param  <T>      数据类型
	 * 	@param 	t		 对象
	 * 	@return	Field[]
	 */
	public static <T> Field[] getFields(T t) {
		return FIELD_PROVIDER.getFields(t);
	}

	/**
	 * 	获取该类下的字段
	 * 	<br>自定义是否忽略静态字段
	 * 		
	 * 	@author Pan
	 * 	@param  <T>      数据类型
	 * 	@param 	t		 对象
	 * 	@param 	ignoreStaticField	true忽略静态字段
	 * 	@return	Field[]
	 */
	public static <T> Field[] getFields(T t, boolean ignoreStaticField) {
		return FIELD_PROVIDER.getFields(t, ignoreStaticField);
	}
	
	/**
	 * 	获取该类下的字段
	 * 	<br>自定义反射缓存
	 * 
	 * 	@author Pan
	 * 	@param  <T>      			数据类型
	 * 	@param 	t					对象
	 * 	@param 	fieldCacheObject	反射缓存
	 * 	@return	Field[]
	 */
	public static <T> Field[] getFields(T t, FieldCacheObject fieldCacheObject) {
		return FIELD_PROVIDER.getFields(t, fieldCacheObject);
	}
	
	/**
	 * 	获取该类下的所有字段
	 * 	<br>返回该集合首个元素的所有字段对象
	 * 	<br>默认忽略静态字段 
	 * 
	 * 	@author Pan
	 * 	@param  <T>     数据类型
	 * 	@param 	list	集合
	 * 	@return	Field[]
	 */
	public static <T> Field[] getFields(List<T> list) {
		return FIELD_PROVIDER.getFields(list);
	}
	
	/**
	 * 	获取该类下的字段
	 * 	<br>自定义是否忽略静态字段
	 * 		
	 * 	@author Pan
	 * 	@param  <T>      			数据类型
	 * 	@param 	list				集合
	 * 	@param 	ignoreStaticField	true忽略静态字段
	 * 	@return	Field[]
	 */
	public static <T> Field[] getFields(List<T> list, boolean ignoreStaticField) {
		return FIELD_PROVIDER.getFields(list, ignoreStaticField);
	}
	
	/**
	 * 	获取该类下的字段
	 * 	<br>自定义反射配置
	 * 
	 * 	@author Pan
	 * 	@param  <T>      			数据类型
	 * 	@param 	list				集合
	 * 	@param 	fieldCacheObject	反射缓存
	 * 	@return	Field[]
	 */
	public static <T> Field[] getFields(List<T> list, FieldCacheObject fieldCacheObject) {
		return FIELD_PROVIDER.getFields(list, fieldCacheObject);
	}
	
	/**
	 * 	获取该类下的所有字段
	 * 	<br>默认忽略静态字段 
	 * 
	 * 	@author Pan
	 * 	@param 	clazz	类
	 * 	@return	Field[]
	 */
	public static Field[] getFields(Class<?> clazz) {
		return FIELD_PROVIDER.getFields(clazz);
	}
	
	/**
	 * 	获取该类下的字段
	 * 	<br>自定义是否忽略静态字段
	 * 		
	 * 	@author Pan
	 * 	@param 	clazz	类
	 * 	@param 	ignoreStaticField	true忽略静态字段
	 * 	@return	Field[]
	 */
	public static Field[] getFields(Class<?> clazz, boolean ignoreStaticField) {
		return FIELD_PROVIDER.getFields(clazz, ignoreStaticField);
	}
	
	/**
	 * 	获取该类下的字段
	 * 	<br>自定义反射配置
	 * 	<br>自定义忽略对象
	 * 		
	 * 	@author Pan
	 * 	@param 	clazz				类
	 * 	@param 	fieldCacheObject	反射缓存
	 * 	@return	Field[]
	 */
	public static Field[] getFields(Class<?> clazz, FieldCacheObject fieldCacheObject) {
		return FIELD_PROVIDER.getFields(clazz, fieldCacheObject);
	}
	
	/**	
	 * 	如果搜索到相对应的name值
	 * 	<br>返回所需要的Field[]
	 * 	<br>已开启访问控制权限
	 * 	
	 * 	@author Pan
	 * 	@param  clazz		类
	 * 	@param 	searchKeys	搜索值
	 * 	@return	List
	 */
	public static List<Field> getFields(Class<?> clazz, String... searchKeys) {
		if (ValidParam.isEmpty(searchKeys)) {
			return Empty.list();
		}
		
		Field[] fields = getFields(clazz);
		
		return CollUtils.newArrayList(thisList ->
			//	先搜索searchKeys参数保证传递值为有序
			IteratorUtils.array(searchKeys, key ->
				IteratorUtils.array(fields, field -> {
					if (StringUtils.eq(field.getName(), key)) {
						thisList.add(field);
					}
				})
			)
		); 
	}
	
	/**
	 * 	获取Field转化为Map格式
	 * 	
	 * 	<br>Key = 字段名
	 * 	<br>Value = Field对象	
	 * 	
	 * 	@author Pan
	 * 	@param  <T>     数据类型
	 * 	@param 	obj		对象
	 * 	@return	Map
	 */
	public static <T> Map<String, Field> getFieldsToMap(T obj) {
		return getFieldsToMap(obj.getClass());
	}

	/**
	 * 	获取Field转化为Map格式
	 * 	
	 * 	<br>Key = 字段名
	 * 	<br>Value = Field对象	
	 * 	
	 * 	@author Pan
	 * 	@param 	clazz	类
	 * 	@return	Map
	 */
	public static Map<String, Field> getFieldsToMap(Class<?> clazz) {
		Field[] fields = getFields(clazz);
		return MapUtils.newHashMap(map -> IteratorUtils.array(fields, field -> map.put(field.getName(), field)), fields.length);
	}
	
	/**
	 * 	根据字段对象获取当前值
	 * 	<br>开启访问权限
	 * 	
	 * 	@author Pan
	 * 	@param  <T>      		数据类型
	 * 	@param 	field			字段
	 * 	@param	obj				对象
	 * 	@return	Object
	 */
	public static <T> Object getFieldValue(Field field, T obj) {
		try {
			setAccessible(field);
			return field.get(obj);
		} catch (Exception e) {
			throw new IllegalArgumentException(StringUtils.format("get field value error cause:{}", e.getMessage()), e);
		}
	}
	
	/**
	 * 	根据字段名获取对应的值
	 * 	<br>开启访问权限
	 * 	
	 * 	@author Pan
	 * 	@param  <T>      	数据类型
	 * 	@param 	obj			对象
	 * 	@param	fieldName	字段名
	 * 	@return	Object
	 */
	public static <T> Object getFieldValue(T obj, String fieldName) {
		Assert.isNotEmpty(fieldName);
		
		Field field = getField(obj, fieldName);
		if (field == null) {
			return null;
		}
		return getFieldValue(field, obj);
	}
	
	/**
	 * 	根据字段名获取对应的值
	 * 	<br>开启访问权限
	 *
	 * 	@author Pan
	 * 	@param 	<T> 		真实数据类型
	 * 	@param  <R>      	返回类型
	 * 	@param 	obj			传递对象
	 * 	@param 	fieldName	字段名
	 * 	@param 	clazz		指定class
	 * 	@return	T
	 */
	@SuppressWarnings("unchecked")
	public static <T, R> R getFieldValue(T obj, String fieldName, Class<R> clazz) {
		Assert.isNotEmpty(fieldName);
		if (obj == null) {
			return null;
		}

		Field field = getField(obj.getClass(), fieldName);
		if (field == null) {
			return null;
		}
		return (R) getFieldValue(field, obj);
	}

	/**	
	 * 	搜索集合对象中的某个字段返回
	 * 	
	 * 	@author Pan
	 * 	@param  <E>      	数据类型
	 * 	@param 	list		集合
	 * 	@param 	fieldName	搜索字段
	 * 	@return	List
	 */
	public static <E> List<Object> getFieldValue(List<E> list, String fieldName) {
		return getFieldValue(list, fieldName, Object.class);
	}
	
	/**	
	 * 	搜索集合对象中的某个字段返回
	 * 	<br>返回指定类型
	 * 
	 * 	@author Pan
	 * 	@param  <E>      	数据类型
	 * 	@param  <R>      	返回类型
	 * 	@param 	list		集合
	 * 	@param 	fieldName	搜索字段
	 * 	@param 	clazz		类
	 * 	@return	List
	 */
	@SuppressWarnings("unchecked")
	public static <E, R> List<R> getFieldValue(List<E> list, String fieldName, Class<R> clazz) {
		Assert.isNotEmpty(fieldName);
		
		if (ValidParam.isEmpty(list)) {
			return Empty.list();  
		}
		
		Field field = FIELD_PROVIDER.getField(ClassUtils.getClass(list), fieldName);
		
		if (field == null) {
			return Empty.list();
		}
		return CollUtils.newArrayList(newList -> IteratorUtils.array(list, t -> newList.add((R) getFieldValue(field, t))), list.size());
	}
	
	/**
	 * 	有序返回该类所有字段属性值
	 * 	
	 * 	@author Pan
	 * 	@param 	<T> 	真实数据类型
	 * 	@param 	bean	对象
	 * 	@return	List
	 */
	public static <T> List<Object> getFieldsValue(T bean) {
		Field[] fields = getFields(bean);
		return CollUtils.newArrayList(list -> IteratorUtils.array(fields, field -> list.add(getFieldValue(field, bean))), fields.length);
	}
	
	/**
	 * 	返回该类所有字段属性值
	 * 	<br>key=字段名,value=值
	 * 	<br>无序返回
	 * 
	 * 	@author Pan
	 * 	@param 	<T> 	真实数据类型
	 * 	@param 	bean	对象
	 * 	@return	Map
	 */
	public static <T> Map<String, Object> getFieldsValueToMap(T bean) {
		Field[] fields = getFields(bean);
		return MapUtils.newHashMap(map -> IteratorUtils.array(fields, field -> map.put(field.getName(), getFieldValue(field, bean))), fields.length);
	}

	/**
	 * 	返回该类所有字段属性值
	 * 	<br>key=字段名,value=值
	 * 	<br>有序返回
	 *
	 * 	@author Pan
	 * 	@param 	<T> 	真实数据类型
	 * 	@param 	bean	对象
	 * 	@return	Map
	 */
	public static <T> Map<String, Object> getFieldsValueToLinkedHashMap(T bean) {
		Field[] fields = getFields(bean);
		return MapUtils.newLinkedHashMap(map -> IteratorUtils.array(fields, field -> map.put(field.getName(), getFieldValue(field, bean))), fields.length);
	}

	/**
	 * 	设置该类下某个字段的值
	 * 	
	 * 	@author Pan
	 * 	@param  <T>      	数据类型
	 * 	@param  <V>      	返回类型
	 * 	@param 	obj			对象
	 * 	@param 	fieldName	字段名
	 * 	@param 	value		值
	 * 	@return V
	 */
	public static <T, V> V setFieldValue(T obj, String fieldName, V value) {
		if (obj == null || value == null) {
			return null;
		}
		
		Field field = getField(obj.getClass(), fieldName);
		if (field == null) {
			return null;
		}
		
		return setFieldValue(field, obj, value);
	}
	
	/**	
	 * 	设置Field字段值
	 * 	
	 * 	@author Pan
	 * 	@param  <T>     数据类型
	 * 	@param  <V>     返回类型
	 * 	@param 	field	字段名
	 * 	@param 	obj		对象
	 * 	@param 	value	值
	 * 	@return	V
	 */
	public static <T, V> V setFieldValue(Field field, T obj, V value) {
		if (field == null || obj == null || value == null) {
			return null;
		}

		if ((!Modifier.isPublic(field.getModifiers()) ||
				!Modifier.isPublic(field.getDeclaringClass().getModifiers()) ||
				Modifier.isFinal(field.getModifiers())) && !field.isAccessible()) {
			setAccessible(field);
		}
		
		try {
			field.set(obj, value);
			return value;
		} catch (Exception e) {
			throw new IllegalArgumentException(StringUtils.format("set field value error cause:{}", e.getMessage()), e);
		}
	}
	
	/**	
	 * 	修改static final字段值
	 * 	
	 * 	@author Pan
	 * 	@param  field		 字段
	 * 	@param  newValue	 值
	 */
	public static void setFieldStaticFinal(Field field, Object newValue) {
		try {
			Field modifiersField = Field.class.getDeclaredField("modifiers");
			
	        setAccessible(field);
	        setAccessible(modifiersField);
	        
	        modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
	        field.set(null, newValue);
		} catch (Exception e) {
			throw new IllegalArgumentException(e.getMessage(), e);
		}
    }
	
	/**
	 * 	Map设置该类下某个一个或多个字段的值
	 * 	
	 * 	@author Pan
	 * 	@param  <T>     返回类型
	 * 	@param  <V>     值类型
	 * 	@param 	clazz	类
	 * 	@param 	params	参数
	 * 	@return	T
	 */
	public static <T, V> T setFields(Class<T> clazz, Map<String, V> params) {
		T newInstance = newInstance(clazz);
		setFields(newInstance, params);
		return newInstance;
	}
	
	/**
	 * 	Map设置该类下某个一个或多个字段的值
	 * 	
	 * 	@author Pan
	 * 	@param  <T>      	数据类型
	 * 	@param  <V>      	值类型
	 * 	@param 	obj			对象
	 * 	@param 	params		参数
	 */
	public static <T, V> void setFields(T obj, Map<String, V> params) {
		if (MapUtils.isEmpty(params)) {
			return ;
		}
		
		Field[] fields = getFields(obj);
		//	设置值
		IteratorUtils.array(fields, field -> setFieldValue(field, obj, params.get(field.getName())));
	}
	
	/**	
	 * 	扫描类是否存在注解 如果存在返回注解值
	 * 	
	 * 	@author Pan
	 * 	@param  <A>      	数据类型
	 * 	@param 	clazz		类
	 * 	@param 	annotation	注解
	 * 	@return	Annotation
	 */
	public static <A> Annotation getClassAnnotation(Class<?> clazz, Class<A> annotation) {
		Annotation[] declaredAnnotations = clazz.getDeclaredAnnotations();
		for (int i = 0, len = declaredAnnotations.length; i < len; i++) {
			Annotation declaredAnnotation = declaredAnnotations[i];
			if (declaredAnnotation.annotationType().equals(annotation)) {
				return declaredAnnotation;
			}
		}
		return null;
	}

	/**	
	 * 	扫描类中方法是否存在某注解
	 * 	<br>存在返回对应注解的{@code List<Method>}
	 * 	<br>多个注解时为(与条件)判断
	 * 
	 * 	@author Pan
	 * 	@param 	clazz			类
	 * 	@param 	annotations		注解
	 * 	@return	List
	 */
	@SafeVarargs
	public static List<Method> getMethodAnnotation(Class<?> clazz, Class<? extends Annotation>... annotations) {
		Method[] methods = getMethods(clazz);
		List<Method> list = null;
		
		for (int i = 0, len = methods.length; i < len; i++) {
			Method method = methods[i];
			if (!scanAnnotationAnd(null, method, annotations)) {
				continue;
			}
			if (list == null) {
				list = CollUtils.newArrayList(len);
			}
			list.add(method);
		}
		return list;
	}
	
	/**		 
	 * 	扫描类中字段是否存在某注解
	 * 	<br>存在返回对应注解的{@code List<Field>}
	 *
	 * 	@author Pan
	 * 	@param 	clazz			类 
	 * 	@param 	annotations		注解
	 * 	@return	List
	 */
	@SafeVarargs
	public static List<Field> getFieldAnnotation(Class<?> clazz, Class<? extends Annotation>... annotations) {
		Field[] fields = getFields(clazz);
		List<Field> list = CollUtils.newArrayList();

		for (int i = 0; i< annotations.length; i++) {
			Class<? extends Annotation> annotation = annotations[i];

			for (int j = 0, len = fields.length; j < len; j++) {
				Field field = fields[j];
				if (getFieldAnnotation(field, annotation) != null) {
					list.add(field);
					break;
				}
			}
		}
		return list;
	}
	
	/**		 
	 * 	扫描类中字段是否存在某注解
	 * 	<br>存在返回对应注解的{@code List<Field>}
	 * 	<br>多个注解时为(与条件)判断
	 *  <br>true为存在
	 * 
	 * 	@author Pan
	 * 	@param  <A>      		数据类型
	 * 	@param 	field			字段对象 
	 * 	@param 	annotation		注解
	 * 	@return	Annotation
	 */
	public static <A> Annotation getFieldAnnotation(Field field, Class<A> annotation) {
		Annotation[] annotations = field.getAnnotations();
		for (int i = 0, len = annotations.length; i < len; i++) {
			Annotation declaredAnnotation = annotations[i];
			if (declaredAnnotation.annotationType().equals(annotation)) {
				return declaredAnnotation;
			}
		}
		return null;
	}

	/**
	 * 	扫描类中字段是否存在某注解
	 * 	<br>存在返回对应注解的{@code List<Field>}
	 *  <br>获取对应注解多条件
	 *
	 * 	@author Pan
	 * 	@param 	clazz			类
	 * 	@param 	annotations		注解
	 * 	@return	List
	 */
	@SafeVarargs
	public static Field getFieldAnnotationAnd(Class<?> clazz, Class<? extends Annotation>... annotations) {
		Field[] fields = getFields(clazz);

		for (int i = 0, len = fields.length; i < len; i++) {
			Field field = fields[i];
			if (scanAnnotationAnd(null, field, annotations)) {
				return field;
			}
		}
		return null;
	}

	/**
	 * 	扫描注解
	 * 	<br> 或条件
	 * 	
	 * 	@author Pan
	 * 	@param  <T>      			数据类型
	 * 	@param 	clazz				类
	 * 	@param 	accessibleObject	方法、字段对象
	 * 	@param 	annotations			注解
	 * 	@return	Annotation
	 */
	@SafeVarargs
	public static <T extends AccessibleObject> Annotation getAnnotationValueOr(Class<?> clazz, T accessibleObject, Class<? extends Annotation>... annotations) {
		if (clazz == null) {
			for (Class<? extends Annotation> annotation : annotations) {
				if (accessibleObject.isAnnotationPresent(annotation)) {
					return accessibleObject.getDeclaredAnnotation(annotation);
				}
			}
		} else {
			//	类
			for (Class<? extends Annotation> annotation : annotations) {
				if (clazz.isAnnotationPresent(annotation)) {
					return accessibleObject.getDeclaredAnnotation(annotation);
				}
			}
		}
		return null;
	}
	
	/**	
	 * 	构造函数
	 * 	<br>方法
	 * 	<br>字段
	 * 	<br>通用开启权限
	 * 	
	 * 	@author Pan
	 * 	@param 	<T>	数据类型
	 * 	@param 	accessibleObject  对象
	 */
	public static <T extends AccessibleObject> void setAccessible(T accessibleObject) {
		if (accessibleObject == null || accessibleObject.isAccessible()) {
			return ;
		}
		accessibleObject.setAccessible(true);
	}
	
	/**	
	 * 	对比参数类型
	 * 	<br>原始参数类型与传递参数类型进行对比是否一致
	 * 	<br>避免原始类与包装类不同
	 * 	<br>用于对比构造函数参数类型与传递参数类型是否一致、invoke方法参数对比等
	 * 	
	 * 	@author Pan
	 * 	@param 	sourceTypes			原始参数类型
	 * 	@param 	callTypes			调用参数类型
	 * 	@return	boolean
	 */
	public static boolean compareParamType(Class<?>[] sourceTypes, Class<?>[] callTypes) {
		//	如果都为空则默认为 空构造函数
		if (ValidParam.isEmpty(sourceTypes) && ValidParam.isEmpty(callTypes)) {
			return true;
		}
		//	避免之后触发NullPointer								
		if ((sourceTypes == null || callTypes == null)
				//	如果参数长度不一致跳过
				|| (sourceTypes.length != callTypes.length)) {
			return false;
		}
		
		//	对比类型
		for (int i = 0, len = sourceTypes.length; i < len; i++) {
			Class<?> sourceParam = sourceTypes[i];
			Class<?> callParam = callTypes[i];
			
			//	首次先对比类型是否一致
			if (ClassTypeUtils.isAssignableFrom(sourceParam, callParam)) {
				return true;
			}
			
			//	如果反射的形参为包装类, 但是这里强转成基本类型了, 方法(method)级采用此类方法可能抛出NosuchMethod异常
			//	验证是否是包装类或者原始类
			if (!ClassTypeUtils.isBasicDataType(sourceParam) || !ClassTypeUtils.isBasicDataType(callParam)) {
				return false;
			}
			Class<?> convertBasicType = ClassTypeUtils.convertBasicType(sourceParam);
			Class<?> convertBasicType2 = ClassTypeUtils.convertBasicType(callParam);
			//	判定此 Class 对象所表示的类或接口与指定的 Class 
			//	参数所表示的类或接口是否相同，或是否是其超类或超接口。如果是则返回 true;否则返回 false。
			//	如果该 Class 表示一个基本类型，且指定的 Class 参数正是该 Class 对象,则该方法返回 true;否则返回 false。 
			//	验证基本类型是否一致
			if (!ClassTypeUtils.isAssignableFrom(convertBasicType, convertBasicType2)) {
				return false;
			}
		}
		return true;
	}
	
	/**
	 * 	验证是否是静态方法修饰
	 * 	
	 * 	@author Pan
	 * 	@param 	clazz			类
	 * 	@param 	methodName		方法名
	 * 	@return	boolean
	 */
	public static boolean isStaticMethod(Class<?> clazz, String methodName) {
		Assert.isNotEmpty(methodName);
		
		Method method = getMethod(clazz, methodName);
		if (method == null) {
			return false;
		}
		return Modifier.isStatic(method.getModifiers());
	}

	/**	
	 * 	是否字段为静态变量
	 * 	
	 * 	@author Pan
	 * 	@param 	field	字段对象
	 * 	@return	boolean
	 */
	public static boolean isStaticField(Field field) {
		return Modifier.isStatic(field.getModifiers());
	}
	
	/**	
	 * 	是否是序列化ID
	 * 	
	 * 	@author Pan
	 * 	@param 	field		字段对象
	 * 	@return	boolean
	 */
	public static boolean isSerialId(Field field) {
		return StringUtils.eq("serialVersionUID", field.getName());
	}
	
	/**
	 * 	反射调用方法
	 * 	<p>
	 * 
	 * 	无参方法
	 *  <br> {@code invoke(MethodInvokeBuilder.builder(Abc.class, "abc")) }
	 *  <br>
	 *  
	 *  <p>
	 *  有参方法
	 * 	<br>
	 * 	 {@code invoke(MethodInvokeBuilder.builder(Abc.class, "abc")}
	 * 	<br>{@code .setCallParams(1)}
	 * 	<br>{@code .setParamType(int.class))}
	 *	
	 * 	@author Pan
	 * 	@param 	methodInvokeBuilder	封装调用对象
	 * 	@return	Object
	 */
	public static Object invoke(MethodInvokeBuilder methodInvokeBuilder) {
		Assert.isNotNull(methodInvokeBuilder);
		return methodInvokeBuilder.build();
	}
	
	/**
	 * 	实例对象
	 * 	
	 * 	@author Pan
	 * 	@param  <T>      	数据类型
	 * 	@param 	clazz		类
	 * 	@param 	params		构造函数参数
	 * 	@return	T
	 */
	public static <T> T newInstance(Class<T> clazz, Object... params) {
		try {
			if (params == null || params.length == 0) {
				return clazz.newInstance();
			}
			//	获取有参构造函数
			Class<?>[] classes = ClassUtils.getClasses(params);
			
			Constructor<T> constructor = getConstructor(clazz, classes);
			if (constructor == null) {
				throw new InstanceException("not found constructor");
			}
			return constructor.newInstance(params);
		} catch (Exception e) {
			throw new InstanceException(StringUtils.format("instance error class{} cause:{}", clazz, e.getMessage(), e));
		}
	}
}
